What's new ========== This page records user-visible changes to the **modern** RISE Toolbox -- new features, behaviour changes, and things you may need to know when upgrading. Newest entries go on top. .. note:: This page covers the modern toolbox only. The legacy toolbox (``RISE_Tbx_Beta``) has its own release notes in ``rise-stable-docs``; the two are never mirrored into each other. Unreleased ---------- - **Fixed: an observed driver of the transition probabilities in a model with occasionally-binding constraints.** Filtering such a model stopped with an index error: the constraint engine evaluated the transition matrix without the driver's value. It now receives it, so time-varying transition probabilities driven by data and constraints such as the zero lower bound can be filtered and estimated together. - **Fixed: the first period of the constrained filter.** ``imm`` updated through the constrained step from inputs set at the end of each period for the next, and nothing set them for the first observed period: its likelihood ignored the constraints. They are now set from the initial distribution whenever it is the stationary one, so the first period is treated like any other. Models whose first period is far from their constraints are unchanged bit for bit; an exact diffuse start, or an initial state given as the first prediction, keep today's update. - **Changed: the steady state of the lead of a growing variable moves with the trend.** In a model with a balanced growth path, ``stst(V{+1})`` written in a dynamic equation was the value of the path at the expansion date, a constant: a hand-written anchor such as ``stst(C{+1})+mcd*(C{+1}-stst(C{+1}))`` then had no balanced growth path for ``mcd < 1`` and the solution drifted without shocks. It is now the moving reference of ``@cognitive_discount``: exogenous unit-root trends at their realized value, the other trends at their previous value grown at trend. For the log price level with ``p = p{-1} + pi``, ``stst(p{+1})+m*(p{+1}-stst(p{+1}))`` is ``p + pis + m*(pi{+1} - pis)``. Models without trends, stationary variables and ``stst()`` of current values or lags are unchanged. See :ref:`stst-of-growing-variables`. - **Fixed: ``'bm'`` on the planner-discount knife-edge.** The solve failed (retcode 30) because the anchor condition has a continuum there; the solution is now the limit of those at nearby planner discounts. See :doc:`/ModelShapes/DSGE/Optimal policy`. - **Fixed: the smoothed shocks of the first period.** They were exactly zero: the filter gave the shocks of the first period an initial covariance independent of the first prediction of the state, which they move. They are now the exact ones. On fs2000, RISE's smoothed shocks match Dynare's in every period; they differed by 6e-4 in the first. The likelihood and the filtered and smoothed variables do not change. - **Changed: the known-regimes filter (``myKnownRegimesFilter``) takes the regime of each period, and refuses what it cannot filter.** In ``filter(m, kf_user_algo = {@myKnownRegimesFilter, regs})``, ``regs(t)`` is the regime of period t: the regime of the solution that produces period t, whose standard deviations the shocks of period t have. The filter used to apply each regime one period late; a path shifted to compensate must now be passed as is. The constant of each period is that of its regime (models whose regimes have different steady states were filtered with the constants of the wrong regimes). The initial state and covariance are those of the regime of the first period instead of an ergodic average; ``kf_user_init`` overrides them. Constraints (unless ``simul_disable_constraints``), news shocks, ``solve_order > 1`` and deterministic exogenous variables raise errors with identifiers ``rise:knownRegimes:*``. With shock standard deviations written as switching parameters the filter is the heteroskedastic filter: see :ref:`known-regime-paths`. - **Changed: the auxiliary equations of an ``@outside_optimization`` block are exempt with it.** The equation RISE adds for a lead or lag beyond one inside a block (``LEAD_1_B{t} = B{t+1}`` for a ``B{t+2}``) was a constraint of every player, with a multiplier zero along the solution, and could raise the feedback warning. It now belongs to the block, in both forms: the exempt players do not include it in their system and take its variable as given (no derivative with respect to it). The solutions are unchanged; the multipliers on those rows are gone. An auxiliary that an equation outside the block shares stays a constraint. See :doc:`/ModelShapes/DSGE/Optimal policy`. - **Changed: one smoother for the regime-switching filters, in which identities written in the model hold.** ``imm``, ``imm_o``, ``gpbn`` (every history length), ``immn`` and ``crskfc`` now smooth pairs of linked regime histories against each pair's own prediction, with Kim's posterior weights. An identity the model states in every regime (a level and its growth rate) now holds in the smoothed path to rounding; before, it was off by up to about 1e-2. Likelihoods and filtered series are unchanged; all smoothed output of switching models changes. ``crskfc``'s default smoother is now this one. See :doc:`/WorkingWithAModel/Filtering`. - **Fixed: on the planner-discount knife-edge, the commitment solution of a regime-switching model is the limit too, rest points included.** The continuation to the limit of the planner's discount started only when the solver reported unit-circle eigenvalues, which the switching solvers never do. It now finds the unit roots in each regime's solved transition of the state variables. Under ``{'m','scl'}`` and ``'bm'`` the expansion points are extrapolated with the decision rules. On a switching tracker model the reporting variable's multiplier is now zero, and the solution equals the model without it. Constant-parameter models, and switching models off the knife-edge, are unchanged. See :doc:`/ModelShapes/DSGE/Optimal policy`. - **New: ``@outside_optimization(home){B_F}``, a block that exempts only the players it names.** The parentheses, refused until now, name the players that are not constrained by the block's equations and take the variables in the braces as given; the other players keep the equations as constraints. The exempt player has no multiplier on those rows and no first-order condition with respect to the variables it takes as given: the game is the one written with the equations in ``@model`` and the variables left out of the exempt player's objective, under commitment, discretion and loose commitment, in Nash and leader-follower games and in ``@state`` games. A block naming every player is the every-player form ``@outside_optimization{W}``. The linear-quadratic solvers still refuse both forms. See :doc:`/ModelShapes/DSGE/Optimal policy`. - **Changed: a constrained update that cycles between two branches takes the one consistent branch, and otherwise fails at once.** Where a constraint binds, ``imm`` iterates its update through the constrained step. When the update kept alternating between two branches of the constraints, it failed after 20 iterations (retcode 314). It now checks each branch's update against the constraints. When exactly one is consistent, the update takes it, and the period is listed in the filter's output field ``resolved_cycle_updates``. When neither or both are, the filter fails with retcode 314 at once. Wherever the update settled before, likelihoods and retcodes are unchanged bit for bit. - **Faster: filtering under constraints.** Three overheads of the constraint engine are gone: the ``max()``/``min()`` of a model's constraints no longer go through name-value parsing, the projection onto the constraints no longer throws and catches an error to look up its tolerance, and a projection whose Gauss-Newton loop only returns to the same points stops at once instead of at its step cap. Likelihoods are unchanged bit for bit. On a switching NK-HANK with a ZLB and borrowing limits, an evaluation with the constraints enforced takes about 45% less time. - **Fixed: ``utils.math_comp.max(A)`` and ``utils.math_comp.min(A)`` with one argument** errored. They now reduce as ``max(A,[],'ComparisonMethod','real')``. - **Fixed: discretion under automatic differentiation.** With ``'solve_derivatives_type','automatic'``, next period's discretionary policy entered the first-order conditions as a constant: its derivatives were lost, and order-2 solutions differed from the symbolic ones. Automatic and symbolic derivatives now give the same solution. - **Fixed: models built at ``max_deriv_order`` 0.** Building a model without symbolic derivatives, to solve it with automatic derivatives, failed with an index out of bounds. It now builds and solves. - **Changed: a plan and ``simul_regime`` that disagree about a regime are an error.** ``simul_regime`` used to overwrite, silently, the regimes a plan fixes (``append(plan, 'regime', t, r)``). Where the two give different regimes for the same period, ``simulate`` now stops with ``RISE:simulate:regimeConflict``, naming the period; where only one gives a regime, or they agree, it is used. The jump-off date is not checked. See :doc:`/WorkingWithAModel/Forecasting and simulation`. - **Changed: a constrained update that fails outright fails the filter (retcode 314).** Where a constraint binds, the filter updates through the constrained step; when that update failed it fell back silently to the Kalman update, so the likelihood was not the constrained model's. It now stops with retcode 314 (``CONSTRAINED_UPDATE_FAILED``), which an estimation treats as an inadmissible draw. An observed variable held at its bound and an ill-conditioned branch keep the Kalman update, as before. On the test models no update fails outright, and likelihoods are unchanged. See :doc:`/WorkingWithAModel/Filtering`. - **Fixed: in ``@transition_functions`` a log variable means its level, as in ``@model``.** The transition matrix read a log variable as its log while the reported series (``zlb_tp_1_2``) read its level, so the two disagreed, and a transition function with a negative power of a log variable divided by zero at the steady state. Every block now reads a log variable as its level. **A model written for the old reading must be rewritten in levels** (``exp(theta*B)`` that stood for ``B^theta`` becomes ``B^theta``). See :doc:`/WorkingWithAModel/Time-varying transition probabilities`. - **Fixed: under constraints, the regime-switching filters predict each regime with that regime's solution.** For each regime of the next period, the constrained prediction was taken in the most likely successor of that regime instead: the same regime when the transition probabilities are constant and persistent, often another one when they vary with the state or a regime stays with probability below 0.5. The prediction then disagreed with the covariance and the update of its branch, and the update through the constrained step fell back to the Kalman update (35 of 78 periods on a test HANK with time-varying probabilities; none now, and ten times faster). Constrained likelihoods of such models can change; models with constant, persistent probabilities are unchanged, bit for bit. Applies to every regime-switching filter, x-at-risk and the reduced models' filter. See :doc:`/WorkingWithAModel/Filtering`. - **Changed: Taylor projection takes the expectation over next period's shocks.** The ``rtp`` paradigm set next period's shock to zero, so its solution had no risk correction at any order. The projection equations now hold in expectation (``rtp.shock_nodes``, a rule exact at the order): at the steady-state anchor order-2 Taylor projection is order-2 perturbation, and re-anchored it carries the same precautionary drift. Under regime switching the regimes' policies now differ by their volatilities. ``'expectation','none'`` restores the old, certainty-equivalent projection; order 1 is unchanged. See :doc:`/WorkingWithAModel/Extending RISE through paradigms`. - **Changed: under the OccBin paradigm a constrained variable lands on its bound when the binding branch is nonlinear in it.** The constant of a binding regime is taken where its constrained variables sit on their bounds, so a rule ``log(1+R) = gam*log(...)`` gives ``R = 0`` at the zero lower bound rather than the tangent value at the steady state. The new option ``'anchor_at_bound',false`` restores the classical OccBin constant. See :doc:`/ModelShapes/DSGE/Occasionally-binding constraints` and the tutorial ``ModelShapes/occbin_bound``. - **New: equations outside the optimization.** An ``@outside_optimization{W}`` block holds equations that are solved with the model but are not constraints of the optimal-policy players, such as a welfare tracker kept for reporting: they carry no multiplier, and the variables in the braces, one per equation, are taken as given by the players. The policy problem is then the one without those equations. A variable taken as given that enters what a player optimizes is reported (``RISE:outside_optimization:feedback``), or refused with ``'outside_optimization_feedback','error'``. Exempting only some players and the linear-quadratic solvers are not available yet. See :doc:`/ModelShapes/DSGE/Optimal policy` (*Equations outside the optimization*) and the tutorial ``OptimalPolicy/OutsideOptimization``. - **Changed: the multiplier charts take the exact trend exponents of the Lagrange multipliers; one numeraire per independent trend.** Under ``geometric_multipliers`` with ``multiplier_charts``, the exponents of the multipliers' trends come from the symmetry of the static system rather than from the solved growth factors, so exponents such as -1 or 0 are exact and zero or negative multipliers get theirs from their first-order conditions (``model_data.diagnostics.multiplier_trends``). ``multiplier_numeraire`` accepts a cellstr, one trending variable per independent trend, such as technology and the price level. The cases the numeraires do not span, multipliers that do not grow as a power law, and models where the exact route is declined are reported with warnings (``rise:multiplier_charts:notSpanned``, ``nonGeometric``, ``exactDeclined``). See :doc:`/ModelShapes/DSGE/Optimal policy` and the tutorial ``OptimalPolicy/NonstationaryRamsey`` (``howto_multiple_trends``). - **Fixed: under discretion the mixed derivatives of next period's policy functions counted several times.** The first-order conditions of discretion and of stochastic replanning carry the derivatives of next period's policy; a mixed second derivative entered them twice (a mixed third one three or six times). Solutions at order 2 and above change wherever the policy functions take two inputs or more; first-order solutions do not. On the quasi-hyperbolic consumer of Krusell and Smith (2003), whose Markov-perfect equilibrium has a closed form, an order-2 solution with a mixed derivative in the policy functions now matches the closed form to 5e-8, where its first-order coefficients were off by up to 0.5. ``sstate_discr_policy_init`` now sets the initial level and first derivatives of the policy functions (it had no effect). See :doc:`/ModelShapes/DSGE/Optimal policy`. - **Changed: every first-order solve goes through the model's configured solver; the linear-quadratic optimal-policy solvers state their own limits.** The self-consistent linearization solved the first orders of its fixed point with the general solver and refused ``loose_commitment`` and ``stochastic_replanning`` by name. It now uses the solver the model is configured with, whichever it is, as ``solve`` does (``rise.engine.dsge_tools.solve.configured_solver``). Each solver applies its own requirements: the linear-quadratic solvers need the lead derivatives of a pair of regimes, divided by the transition probability, to depend on the next regime only, and stop with ``RISE:looseCommitment:leadBlockDependsOnPreviousRegime`` (or ``RISE:stochasticReplanning:...``) when the matrices they are given do not have that structure; above order 1 they stop with ``RISE:looseCommitment:firstOrderOnly`` (or ``RISE:stochasticReplanning:firstOrderOnly``). On a linear-quadratic planner where the structure holds, loose commitment under ``{'m','scl'}`` gives the general solver's answer under ``{'m','scl'}``. Nothing changes under ``'m'``. See :doc:`/ModelShapes/DSGE/Optimal policy`. - **Changed: the self-consistent linearization and the Barthélemy-Marx anchors solve optimal-policy models.** ``{'m','scl'}`` and ``'bm'`` were refused on any model with an ``@optimization_problem``. A perturbation scheme does not depend on where the equations come from: the first-order conditions are now re-anchored like any other equations, under commitment, under discretion and wherever the commitment parameter switches, at every order, and with a common steady state both types return plain ``'m'``. Under discretion the policy functions of next period's regime, which the first-order conditions carry, are evaluated where the self-consistent linearization puts the leads, at the transition points; under ``'m'`` nothing changes. See :doc:`/ModelShapes/DSGE/Perturbation types` and :doc:`/ModelShapes/DSGE/Optimal policy`. - **Fixed: Taylor projection's analytical Jacobian follows the lead point; a re-anchored root far from the policy is rejected.** The model's derivatives are evaluated where the next period's policy lands, which every coefficient moves; ``rtp.jacobian_analytical`` held them fixed (2.3% off the numerical Jacobian, and order-3 Newton stalled where a root exists). With the exact Jacobian, Newton beyond a fold of the order-2 equations in levels converged to absurd roots, so a converged re-solve is now kept only if today's policy at the new state stays within ``reanchor_max_jump`` (new option of ``rtp.paradigm``, default 0.5) of the last converged policy there; otherwise the step warns and reuses the last converged policy. In levels, order 3 now converges at every step from 0.9 to 0.3 of the steady-state capital. Written in logs (``@log_vars``), the growth model keeps the root of its projection equations everywhere, and order-2 Taylor projection is 40 to 450 times more accurate than order-2 perturbation in logs. Write models in logs for Taylor projection far from the steady state. See :doc:`/WorkingWithAModel/Extending RISE through paradigms`. - **Fixed: Taylor projection differentiates the next period's policy where the state lands.** The projection residual used the next period's policy and its derivatives at that policy's own anchor, not where the state lands one period later; the two coincide only at a steady-state anchor of a constant-parameter model. Re-anchored order-2 solutions were therefore less accurate than order-2 perturbation near the steady state (on a growth model started at 90% and 70% of its steady-state capital, largest consumption errors of 0.060% and 0.536% of the steady state against 0.006% and 0.188%); they are now more accurate (0.0033% and 0.138%). Order 3 is as accurate as order-3 perturbation or better from 90% down to 30%. From half the steady-state capital or less, the order-2 projection equations have no root near the policy: those re-solves warn and reuse the last converged policy, and order 3 is the order to use. See :doc:`/WorkingWithAModel/Extending RISE through paradigms`. - **Changed: the RLL paradigm solves each local system with QZ and keeps its own constant by default.** The defaults of ``rll.paradigm`` are now ``'solver', 'rise_qz'`` (was ``'fi'``) and ``'use_steady_state', false`` (was ``true``); both old values remain options. Functional iteration, capped at 100 iterations, failed at every re-linearization of the growth model far from the steady state, so RLL silently equaled first order apart from one warning; with ``use_steady_state`` true the step applied the local slopes around the global steady state, which was less accurate than first order. From capital at 0.9, 0.7, 0.5, 0.4 and 0.3 times its steady state, the largest error in consumption against perfect foresight (% of the steady state) is now 0.07, 0.73, 2.25, 3.28 and 4.27, against 0.11, 1.16, 3.76, 5.94 and 9.05 at first order. At an occasionally binding bound the local system has no unique stable solution, so RLL keeps the previous local solution there, as before. See :doc:`/WorkingWithAModel/Extending RISE through paradigms`. - **Fixed: each simulation under the RLL paradigm starts from the solved local policy.** ``rll.paradigm`` updated its stored solution in place, so a simulation started from the local policy the previous one ended with and the same simulation run twice could give two paths. Each simulation now works on its own copy, as under ``rtp.paradigm``. See :doc:`/WorkingWithAModel/Extending RISE through paradigms`. - **Changed: a lead that a lag multiplies in a constraint of an optimal policy problem gets its own expectation variable.** In ``b{t} = b{t-1}/betta*(1+0.1*pie{t+1}) + ...`` the first-order condition for ``b`` would carry ``pie{t+2}``. RISE now gives ``pie{t+1}`` the variable ``LEAD_1_pie`` before it derives the conditions, as if ``EPIE{t} = pie{t+1}`` had been declared in the model. Solutions under commitment are unchanged up to terms of higher order; under discretion and stochastic replanning the solution is now that of the expectation form, which solves much faster. Terms in which a lag and a lead interact nonlinearly are left as written. See :doc:`/ModelShapes/DSGE/Optimal policy` ("A lead that a lag multiplies"). - **Fixed: re-anchored Taylor projection from a state far from the steady state.** Under ``rtp.paradigm`` (re-anchoring is the default), a growth model started at half its steady-state capital took a path on which consumption jumped up and capital ran down: the first re-solve started from the steady-state policy and converged to another root of the projection equations. Each re-solve now starts from the current policy evaluated at the new state, and only the states of the date-0 vector matter. The solved model also kept the anchors of the last simulation, so running the same simulation again could give another path; every simulation now starts from the solved polynomial. See :doc:`/WorkingWithAModel/Extending RISE through paradigms`. - **Fixed: the heterogeneous-agent steady-state engine no longer runs away.** On a Huggett household with a borrowing limit of -2, the Anderson-accelerated time iteration of ``rise.engine.dsge_tools.sstate.het.engine`` could throw the policy to absurd values (steps of 4e35) and then sweep slowly without end. A mixed step much longer than the plain one is no longer taken, a sweep whose step blows up restarts from the best iterate, and repeated blow-ups stop the solve with the warning ``het:engine:diverged``. See :doc:`/ModelShapes/DSGE/Heterogeneous agents`. - **Fixed: a plan with free shocks runs over its whole span on a regime-switching model.** On a regime-switching model, a plan whose shocks are free (``NaN``) holds nothing after the jump-off, the regimes being left to the chain, and its database lost those dates: ``simulate`` returned the jump-off alone, and a conditioned plan stopped after its last condition. The plan's database now keeps every date. Single-regime models were not affected. See :doc:`/WorkingWithAModel/Simulation plans`. - **Fixed: simulate honors ``simul_history_end_date`` with a plain database, and forecast draws its shocks under ``forecast_shock_uncertainty``.** ``simulate`` ignored the date and started at the database's first date, pinned to the data after it. When the history runs past the database's first date, the simulation now jumps off at the date from the plan ``simplan.from_history`` generates out of the history, as ``forecast`` does. A database that starts at the date is a conditioning database, as before. The shocks of such a plan are now drawn under shock uncertainty (the constraint-enforcing shocks excepted); before, they were pinned, so a forecast from a database gave the same path whatever ``forecast_shock_uncertainty`` said. ``simplan.from_history`` takes the regime and the shocks as optional arguments and no longer fails when the deepest lag predates the data. See :doc:`/WorkingWithAModel/Forecasting and simulation` ("Starting from history"). - **Fixed: simulate takes a recursive plan under a solve paradigm.** A plan built with ``'recursive', true`` carries a second page, and under a solve paradigm (for example the piecewise-linear paradigm on a model with a lower bound) ``simulate`` failed with a size mismatch in the sub-step forecast. A paradigm steps with the shocks of the model's own anticipation horizon: later pages that announce nothing are now dropped, so the recursive plan runs as surprises, and a page that announces something beyond the horizon is refused with ``RISE:simulation:planExceedsParadigmHorizon``. Under ``simulate``, page-1 entries are surprises whether the plan is recursive or not. See :doc:`/WorkingWithAModel/Surprises and announcements` ("Under simulate"). - **Fixed: the historical decomposition of a VAR gives the constant its own column.** ``historical_decomposition`` read the constant of a VAR from a place where the solver leaves zero, so the ``const`` column was zero and the structural-shock columns absorbed the constant (the columns still added up to the data). The columns are now ``init`` (the initial lags propagated), ``const``, one per deterministic variable, and one per structural shock, which contain the shocks' contributions only; they add up to the data. With regime switching the regimes are weighted by the smoothed regime probabilities and the output has one page instead of one per regime. ``residuals`` and ``structural_shocks`` no longer contain the constant either. Results change for every VAR with a constant and for every switching VAR. See :doc:`/ModelShapes/Main Reduced form VAR Modeling`. - **Fixed: tuning the independence sampler maximizes its acceptance rate.** With ``do_tuning``, ``imh`` used the random walk's rule (shrink the scale until the acceptance rate reaches 0.234), which collapses an independence proposal: on a multimodal target the scale fell to about 1e-200. It now searches the scale ``c0*2^k`` that maximizes the acceptance rate and fixes it; on Gaussian targets it lands within a fifth of the best scale. Warnings ``rsamplers:imhTuningFailed`` and ``rsamplers:imhTuningAtSearchEdge`` flag a search that cannot succeed. The random walk is unchanged. See :doc:`/Estimation/Posterior simulation` ("Tuning the proposal scale"). - **Changed: the Choleski identification of a reduced-form VAR follows the order in which the variables were declared.** ``identify(m, 'choleski', shock_names)`` and ``identification`` used to run the recursion in RISE's alphabetical order of the variables; they now follow the list given to ``rfvar_model`` (units, then variables, for ``prfvar_model``), as a recursive ``svar_model`` does. Shock *k* belongs to the *k*-th declared variable and takes the *k*-th name; the new option ``'ordering'`` sets another order. An unidentified reduced-form VAR uses the same recursive factor. Results change unless the variables were declared alphabetically; ``'ordering', sort(variables)`` reproduces the old recursion. Also, ``irf`` now labels the responses by shock slot, so it always agrees with the variance and historical decompositions, including with fewer names than variables. See :doc:`/ModelShapes/Main Reduced form VAR Modeling`. - **Changed: template differentiation is the default.** The construction option ``template_diff`` is now ``true``: every model is differentiated one distinct expression at a time, and an equation with no repeated term is differentiated as before. Same derivatives (to rounding) at every order, with and without regime switching. ``dsge_model(file, 'template_diff', false)`` keeps the standard path. See :doc:`/ModelShapes/DSGE/Template differentiation`. Release 20260831 ---------------- - **New: template differentiation, construction option ``template_diff``.** Models that repeat a few equations -- the cells of a heterogeneous-agent model, the countries or sectors of a loop-generated model, or copies typed out by hand -- are differentiated one distinct expression at a time: RISE finds the terms that are the same expression up to a renaming of variables and parameters, differentiates each once, and evaluates its derivatives for all copies in one vectorized call. Nothing to annotate: ``dsge_model(file, 'template_diff', true)``. Same derivatives as before (to rounding) at every order, with regime switching (constant or time-varying probabilities) and in disk mode. On a two-asset HANK model with 150 cells, differentiation falls from 655 s to 40 s and peak memory from 29.8 GB to 5.2 GB; Jacobian evaluation is 30 to 230 times faster across the models measured. Off by default. See :doc:`/ModelShapes/DSGE/Template differentiation`. Tests: ``models/dsge/template_diff``; tutorial: ``ModelShapes/template_differentiation``. - **Fixed: options given inside the model cell no longer discard the name-value options.** ``dsge_model({file, name, value}, name2, value2)`` rebuilt the construction options from the cell alone, silently dropping ``name2`` (e.g. ``'smooth_kinks', false``). The cell's names and values are now validated and merged with the name-value options; a runtime option in the cell, an unknown name, or the same option with two different values is an error. Options are meant to be passed as name-value arguments; cells holding the model line by line, several snippets or several files are unchanged. - **New: ``rise.microfound`` derives Kuhn-Tucker (inequality) constraints.** ``.subject_to(irrev="I >= 0")`` used to be accepted and then silently dropped from the derived model -- you got a clean solution to the UNCONSTRAINED problem, with no error and no warning. Inequalities are now normalized to their ``g <= 0`` side, given a multiplier ``_lambda_